﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AIProject.AI;

namespace AIProject.Pylos
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            GameAgent agent1 = null;
            GameAgent agent2 = null;
            StreamWriter[] writers = new StreamWriter[2];

            Pylos game;
            Percept p;
            String[] toWrite = new String[2];
            toWrite[0] = "";
            toWrite[1] = "";

            try
            {
                writers[0] = new StreamWriter("Time.csv");
                writers[1] = new StreamWriter("Nodes.csv");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.In.Read();
                Environment.Exit(0);
                return;
            }

            int games = 0;
            int moves = 0;

            if (args.Length == 3 && args[0] == "record")
            {
                if (args[1] == "1")
                {
                    agent1 = new AlphaBetaGameAgent(true);
                    agent2 = new RandomGameAgent(1200052011);
                    Console.WriteLine("Alpha-Beta Selected");
                }
                else if (args[1] == "2")
                {
                    agent1 = new IDAlphaBetaGameAgent(true);
                    agent2 = new RandomGameAgent(1200052011);
                    Console.WriteLine("IDAlpha-Beta Selected");
                }
                else if (args[1] == "3")
                {
                    agent1 = new IDAlphaBetaAITransGameAgent(true);
                    agent2 = new RandomGameAgent(1200052011);
                    Console.WriteLine("IDAlpha-BetaTrans Selected");
                }
                else if (args[1] == "4")
                {
                    agent2 = new RandomGameAgent(1200052011);
                    Console.WriteLine("Random Selected");
                }

                Console.WriteLine(Int32.Parse(args[2]) + " games selected");

                while (games < Int32.Parse(args[2]))
                {
                    toWrite[0] = "";
                    toWrite[1] = "";

                    game = new Pylos();
                    p = game.getPercept();
                    moves = 0;

                    Console.WriteLine("Game " + (games + 1));

                    //if (args[1] == "3")
                    //{
                    //    ((IDAlphaBetaAITransGameAgent)agent1).reset();
                    //}

                    while (true)
                    {
                        if (p.State.WhiteToMove)
                        {
                            if (agent1 != null)
                            {
                                try
                                {
                                    sw.Start();
                                    game.update(agent1.getAction(p));
                                    sw.Stop();
                                }
                                catch (InvalidOperationException e)
                                {
                                    Console.WriteLine(e.Message);
                                    Console.WriteLine(e.StackTrace);
                                    Console.In.Read();
                                    Environment.Exit(0);
                                }
                            }
                            else
                            {
                                game.update(agent2.getAction(p));
                            }
                        }
                        else
                        {
                            game.update(agent2.getAction(p));
                        }

                        p = game.getPercept();

                        if (p.State.WhiteWon || p.State.BlackWon || p.State.Tie)
                        {
                            if (!p.State.WhiteToMove && agent1 != null)
                            {
                                toWrite[0] += sw.ElapsedMilliseconds.ToString();
                                toWrite[1] += agent1.Nodes.ToString();
                            }
                            else if (agent1 == null)
                            {
                                toWrite[1] += agent2.Nodes.ToString();
                            }

                            moves++;

                            if (!p.State.Tie)
                            {
                                for (int i = (moves / 2); i <= 125; i++)
                                {
                                    toWrite[0] += " ,";
                                }
                            }

                            if (p.State.WhiteWon)
                            {
                                toWrite[0] += "1";
                            }
                            else if (p.State.BlackWon)
                            {
                                toWrite[0] += "-1";
                            }
                            else
                            {
                                toWrite[0] += "0";
                            }

                            sw.Reset();
                            break;
                        }
                        else if (!p.State.WhiteToMove && agent1 != null)
                        {
                            toWrite[0] += sw.ElapsedMilliseconds.ToString() + ",";
                            toWrite[1] += agent1.Nodes.ToString() + ",";
                        }
                        else if (agent2 == null)
                        {
                            toWrite[1] += agent2.Nodes.ToString() + ",";
                        }

                        sw.Reset();
                        moves++;
                    }
                    games++;
                    writers[0].WriteLine(toWrite[0]);
                    writers[1].WriteLine(toWrite[1]);
                }
                Console.In.Read();

                writers[0].Close();
                writers[1].Close();
            }
            else
            {
                agent1 = new IDAlphaBetaAITransGameAgent(true);
                agent2 = new RandomGameAgent();

                game = new Pylos();
                p = game.getPercept();

                game.print();

                while (!p.State.BlackWon && !p.State.WhiteWon && !p.State.Tie)
                {
                    Console.In.Read();
                    Action a = null;
                    Console.WriteLine("*******************************************************************************");

                    if (p.State.WhiteToMove)
                    {
                        try
                        {
                            sw.Start();
                            a = agent1.getAction(p);
                            sw.Stop();
                        }
                        catch (InvalidOperationException e)
                        {
                            Console.WriteLine(e.Message);
                            Console.WriteLine(e.StackTrace);
                            Console.In.Read();
                            Environment.Exit(0);
                        }
                    }
                    else
                    {
                        a = agent2.getAction(p);
                    }

                    //Console.WriteLine(sw.ElapsedMilliseconds);
                    sw.Reset();

                    Console.WriteLine((p.State.WhiteToMove) ? "White's Moves\n" : "Black's Moves\n");

                    game.update(a);
                    for (int i = 0; i < 3; i++)
                    {
                        if (a[i] != null)
                        {
                            Console.WriteLine("Move " + (i + 1));
                            Console.WriteLine("\tSource (" + getChar(a[i].Source.X) + ", " + a[i].Source.Y + ")");
                            Console.WriteLine("\tDestination (" + getChar(a[i].Destination.X) + ", " + a[i].Destination.Y + ")");
                        }
                    }

                    game.print();
                    Console.WriteLine("*******************************************************************************");

                    p = game.getPercept();
                    Console.In.Read();
                }

                game.print();
            }
        }

        static string getChar(int move)
        {
            switch (move)
            {
                case -1:
                    {
                        return "-1";
                    }

                case 0:
                    {
                        return "a";
                    }

                case 1:
                    {
                        return "b";
                    }

                case 2:
                    {
                        return "c";
                    }

                case 3:
                    {
                        return "d";
                    }

                case 4:
                    {
                        return "e";
                    }

                case 5:
                    {
                        return "f";
                    }

                case 6:
                    {
                        return "g";
                    }

                case 7:
                    {
                        return "h";
                    }

                case 8:
                    {
                        return "i";
                    }

                case 9:
                    {
                        return "j";
                    }
            }
            return "-1";
        }
    }
}
